package cn.zzp.basic.service.impl;

import cn.zzp.basic.constant.VerifyCodeConstants;
import cn.zzp.basic.exception.BusinessException;
import cn.zzp.basic.service.VerifyCodeService;
import cn.zzp.basic.util.StrUtils;
import cn.zzp.basic.util.VerifyCodeUtils;
import cn.zzp.user.domain.User;
import cn.zzp.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author Administrator
 * @description:
 * @date 2022/7/27 19:07
 */
@Service
public class VerifyCodeServiceImpl implements VerifyCodeService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserMapper userMapper;

    @Override
    public String getVerifyCode(String key) {

        if (StringUtils.isEmpty(key)) {
            throw new BusinessException("业务繁忙，请稍后再试");
        }

        String code = StrUtils.getComplexRandomString(4);

        redisTemplate.opsForValue().set(key,code,3, TimeUnit.MINUTES);

        return VerifyCodeUtils.verifyCode(100,40,code);

    }

    /**
     * 发送验证码短信
     * @param map
     */
    @Override
    public void smsCode(Map<String, Object> map) {
        String phone = map.get("phone").toString();
        String imageCode = map.get("imageCode").toString();
        String imageCodeKey = map.get("imageCodeKey").toString();

        // 1. 判断参数有效
        if (StringUtils.isEmpty(phone)) {
            throw new BusinessException("手机号不能为空");
        }
        if (StringUtils.isEmpty(imageCode)) {
            throw new BusinessException("图形验证码不能为空");
        }

        if (StringUtils.isEmpty(imageCodeKey)){
            throw new BusinessException("请刷新图形验证码重新获取输入");
        }

        // 2. 判断图片验证码正确
        Object imageCodeValue = redisTemplate.opsForValue().get(imageCodeKey);
        if (imageCodeValue == null) {
            throw new BusinessException("图形验证码过期，请重新获取输入");
        }
        if (!imageCodeValue.toString().equalsIgnoreCase(imageCode)){
            throw new BusinessException("图形验证码输入错误，请重新输入");
        }

        // 3. 判断手机号是否被注册
        User user = userMapper.queryByPhone(phone);
        if (user != null) {
            throw new BusinessException("手机号已注册，请登录");
        }

        // 4. 判断验证码是否有效
        //redis存值格式：key[18708146200:register] : value[code:time]
        Object value = redisTemplate.opsForValue().get(phone + VerifyCodeConstants.PHONE_REGISTER_SUFFIX);
        String code = null;
        // 如果为空，说明过期或者第一次点击发送
        if (value == null) {
            code = StrUtils.getComplexRandomString(6);
        }else {
            // 如果有值，需要判断是否超过一分钟

            Long time = Long.parseLong(value.toString().split(":")[1]);
            // 小于1分钟不能发送
            if (System.currentTimeMillis() - time <= 1*60*1000){
                throw new BusinessException("请勿重复发送");
            }else{
                // 大于一分钟
                code = value.toString().split(":")[0];
            }
        }
        // 将code值存入redis
        redisTemplate.opsForValue().set(phone + VerifyCodeConstants.PHONE_REGISTER_SUFFIX,
                                        code + ":" + System.currentTimeMillis(),
                                        3,TimeUnit.MINUTES);

        // 5. 发送短信
        //SmsUtils.sendSms(phone,"您的验证码为：" + code + "，请在三分钟内使用" ); // 测试短信有限，暂时先打印
        System.out.println("您的验证码为：" + code + "，请在三分钟内使用");
    }

    @Override
    public void binderSmsCode(Map<String, String> map) {
        String phone = map.get("phone");

        // 空值校验
        if (StringUtils.isEmpty(phone)) {
            throw new BusinessException("电话号码不能为空");
        }

        // 判断验证码是否过期
        Object obj = redisTemplate.opsForValue().get(phone + VerifyCodeConstants.WXBINDER);
        String code = null;
        if (obj == null){// 验证码过期或者首次登录

            code = StrUtils.getComplexRandomString(6);

        }else { // 验证码没过期
            // 判断是否超时
            Long time = Long.parseLong(obj.toString().split(":")[1]);
            if (System.currentTimeMillis() - time <= 1*60*1000){
                throw new BusinessException("请勿频繁点击发送");
            }else {
                code = obj.toString().split(":")[0];
            }
        }
        // 存入redis中
        redisTemplate.opsForValue().set(
                phone + VerifyCodeConstants.WXBINDER,
                code + ":" + System.currentTimeMillis(),
                3, TimeUnit.MINUTES
        );

        // 发送短信 发送短信需要收费，开发阶段直接打印即可
        // SmsUtils.sendSms(phone, "您的验证码为：" + code + "，请在三分钟内使用" );
        System.out.println("您的验证码为：" + code + "，请在三分钟内使用");
    }
}
